package com.patternity.dotgraph;

import java.io.File;
import java.util.List;
import java.util.Properties;

import com.patternity.dotgraph.DotGraph.AbstractAssociation;
import com.patternity.dotgraph.DotGraph.AbstractNode;
import com.patternity.dotgraph.DotGraph.Digraph;
import com.patternity.model.Element;
import com.patternity.model.Model;
import com.patternity.model.Relation;

/**
 * The engine that renders UML diagrams using Graphviz dot, based on the given
 * model and the given design declarations
 * 
 * @author cyrille martraire
 */
public class DotDiagramWeaver {

	public final static String simpleName(final String name) {
		final int index = name.lastIndexOf('.');
		return index == -1 ? name : name.substring(index + 1);
	}

	public static void render(final String name, final Model displayModel) {
		final DotGraph graph = new DotGraph(name);
		final Digraph digraph = graph.getDigraph();

		for (final Element element : displayModel.elements()) {
			final String elementName = element.getName();
			final AbstractNode node = digraph.addNode(element)
					.setLabel(simpleName(elementName)).setComment(elementName)
					.setOptions(DotGraph.CLASS_NODE_OPTIONS);
			for (final String stereotype : element.getStereotypes()) {
				node.addStereotype(stereotype);
			}
		}
		for (final Relation relation : displayModel.relations()) {
			final String relationName = relation.getName();
			final String style = edgeStyle(relation.getStereotypes());// DotGraph.ASSOCIATION_EDGE_STYLE;

			final boolean reverse = style
					.equalsIgnoreCase(DotGraph.EXTENDS_EDGE_STYLE);
			final AbstractAssociation association = reverse ? digraph
					.addAssociation(relation.getTo(), relation.getFrom())
					: digraph.addAssociation(relation.getFrom(),
							relation.getTo());
			association.setLabel(relationName).setComment(relationName)
					.setOptions(style);
		}
		final String content = graph.render().trim();

		final File file = new File("patternitydot.properties");
		final Properties p = DotRenderer.loadProperties(file);

		final DotRenderer renderer = new DotRenderer(p);
		// System.out.println(content);
		renderer.toImage(name, content);
	}

	private static String edgeStyle(final List<String> stereotypes) {
		for (final String stereotype : stereotypes) {
			// association.add(stereotype);
			if (stereotype.equalsIgnoreCase(Relation.GENERALISATION)) {
				return DotGraph.EXTENDS_EDGE_STYLE;
			}
			if (stereotype.equalsIgnoreCase(Relation.INSTANTIATION)) {
				return DotGraph.INSTANTIATION_EDGE_STYLE;
			}
		}
		return DotGraph.ASSOCIATION_EDGE_STYLE;
	}
}
